#include "CenterService.h"
#include "Server/CenterServiceFactory.h"
#include "base/core/lua_parser.h"
#include "base/core/os/debug.h"
#include "base/core/Profiler.h"
#include "base/core/random.h"
#include "Common/Utility/ServerTime.h"
#include "Common/Utility/TimeUtility.h"
#include "Common/Utility/ServiceUtility.h"
#include "Active/ActiveCharacterMgr.h"
#include "Cache/OfflineCharacterDataMgr.h"
#include "Script/ScriptMgr_CS.h"
#include "ProtoBuffer/AllProtocol.h"
#include "Active/ActiveCharacterMgr.h"
#include "RelationMgr/RelationMgr.h"
#include "ChatCenter/ChatCenter.h"
#include "ServerModule/CenterServerModuleMgr.h"
#include "MailCenter/MailManager.h"
#include "Duplicate/CenterDuplicateMgr.h"
#include "PointTurn/PointTurnMgr.h"
#include "Camp/CampMgr.h"
#include "AccountMgr/CenterAccountMgr.h"
#include "SceneMgr/CenterSceneMrg.h"
#include "AccountMgr/CenterAccountMgr.h"
#include "SceneMgr/CenterSceneMrg.h"
#include "Room/RoomMgr.h"
#include "Team/TeamManager.h"
#include "Global/GlobalMgr.h"
#include "Auctioneer/CenterAuctioneerMgr.h"
#include "RankingList/RankingListMgr.h"
#include "GM/GMManager.h"
#include "Arena/ArenaMgr.h"
#include "MirrorMgr/MirrorMgr.h"
#include "QueryMgr/QueryMgr.h"
#include "Auctioneer/CenterAuctioneerMgr.h"
#include "Union/UnionMgr.h"
#include "EscortMgr/EscortMgr.h"
#include "MallCenter/MallManager.h"
#include "ActivityMgr/ActivityMgr.h"
#include "WebCenterMgr/WebCenterMgr.h"
#include "Common/ErrCollect/ErrCollect.h"
#include "Common/TableData/ConstantConstantCfg.h"
#include "PayCenterMgr/PayCenterMgr.h"
#include "Compete/CompeteMgr.h"
#include "Notify/CNotifyMgr.h"

#ifdef _MSC_VER
#pragma warning(disable:4100)
#endif

namespace
{
	static const char s_config_file[] = "./config.lua";
}

Service*  MakeCenterService()
{
	return CenterService::Instance();
}

void  DeleteCenterService(Service* service)
{
	_UNUSE(service);
	CenterService::Destroy();
}

CenterService::CenterService()
	: Service(CENTER_SERVER)
	, m_pMessageDispatch(nullptr)
	, m_dbProxyServer()
	, m_logServer()
	, m_syncStateTick(0)
	, m_lastDayChangeTime(0)
	, m_zid(0)
	, m_bOpenGMFlag(false)
	, m_openTime(0)
	, m_dayCountFromOpen(0)
	, m_checkPing(false)
{
	m_logicPing.clear();
	m_gateConnectMap.clear();
	m_logicSessionMap.clear();
}

CenterService::~CenterService()
{}

bool CenterService::Init(Net* net, const char* configFile)
{
	bool result = false;
	bool retCode = false;
	uint64_t curTime = 0;
	
	MMO_ASSERT(net);
	m_net = net;

	m_lastDayChangeTime = ServerTime::UnixSec();
	m_curDay = Time::GetLocalDate().year * 365 + Time::GetLocalDate().yday;

	m_pMessageDispatch = new MessageDispatch(this);
	MMOLOG_PROCESS_ERROR(nullptr != m_pMessageDispatch);

	MMOLOG_PROCESS_ERROR(g_MakeCenterServerModuleMgr());
	MMOLOG_PROCESS_ERROR(g_GetCenterServerModuleMgr()->Init());
	
	retCode = _LoadConfig(configFile);
	MMOLOG_ASSERT_EXIT(retCode);

	curTime = g_GetGlobalServerTime()->UnixSec();
	_CalcDayCountFromOpen(curTime);

	MMOLOG_PROCESS_ERROR(g_MakeCSScriptMgr());
	if (!g_GetCSScriptMgr()->Init()) 
	{
		LogErrPrint("[center] script mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeActiveCharacterMgr());
	retCode = g_GetActiveCharacterMgr()->Init();
	MMOLOG_ASSERT_EXIT(retCode);


	MMOLOG_PROCESS_ERROR(g_MakeOfflineCharacterDataMgr());
	if (!g_GetOfflineCharacterDataMgr()->Init())
	{
		LogErrPrint("[center] offline character data mgr init fail");
		goto Exit0;
	}


	MMOLOG_PROCESS_ERROR(g_MakeCenterDuplicateMgr());
	if (!g_GetCenterDuplicateMgr()->Init())
	{
		LogErrPrint("[center] center duplicate mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeRoomMgr());
	if (!g_GetRoomMgr()->Init())
	{
		LogErrPrint("[center] center room mgr init fail");
		goto Exit0;
	}	

	MMOLOG_PROCESS_ERROR(g_MakeChatCenter());
	if (!g_MakeChatCenter()->Init())
	{
		LogErrPrint("[center] chat center mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeRelationMgr());
	if (!g_MakeRelationMgr()->Init())
	{
		LogErrPrint("[center] relation center mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeMailMgr());
	if (!g_MakeMailMgr()->Init())
	{
		LogErrPrint("[center] mail center mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeCampMgr());
	if (!g_GetCampMgr()->Init())
	{
		LogErrPrint("[center] camp center mgr init fail");
		goto Exit0;
	}
	//�̳ǳ�ʼ��Ҫ�ŵ�����֮ǰ������������ݵ�ʱ�������̳ǽӿ�
	MMOLOG_PROCESS_ERROR(g_MakeMallMgr());
	if (!g_GetMallMgr()->Init())
	{
		LogErrPrint("[center] mall center mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeTeamMgr());
	if (!g_GetTeamMgr()->Init())
	{
		LogErrPrint("[center] team center mgr init fail");
		goto Exit0;
	}

	MMOLOG_PROCESS_ERROR(g_MakeGlobalMgr());
	if (!g_GetGlobalMgr()->Init())
	{
		LogErrPrint("[center] global center mgr init fail");
		goto Exit0;
	}	

	MMOLOG_PROCESS_ERROR(g_MakeCenterAuctioneerMgr());
	if (!g_GetCenterAuctioneerMgr()->Init())
	{
		LogErrPrint("[center] auceioneer center mgr init fail");
		goto Exit0;
	}

	//���а� (���а�һ��Ҫ�ڹ���֮ǰ��ʼ��, ������������ÿ�ܺ�ÿ�ո��µģ��п����й����������������)
	MMOLOG_PROCESS_ERROR(g_MakeRankingListMgr());
	if (!g_GetRankingListMgr()->Init())
	{
		LogErrPrint("[center] rankingList mgr init fail");
		goto Exit0;
	}
	//gm
	MMOLOG_PROCESS_ERROR(g_MakeGMMgr());
	if (!g_GetGMMgr()->Init())
	{
		LogErrPrint("[logic] gm mgr init fail");
		goto Exit0;
	}

	//������
	MMOLOG_PROCESS_ERROR(g_MakeArenaMgr());
	if (!g_GetArenaMgr()->Init())
	{
		LogErrPrint("[center] arena mgr init fail");
		goto Exit0;
	}

	//���������
	MMOLOG_PROCESS_ERROR(g_MakeMirrorMgr());
	if (!g_GetMirrorMgr()->Init())
	{
		LogErrPrint("[center] mirror mgr init fail");
		goto Exit0;
	}

	//��ѯ������
	MMOLOG_PROCESS_ERROR(g_MakeQueryMgr());
	if (!g_GetQueryMgr()->Init())
	{
		LogErrPrint("[center] query mgr init fail");
		goto Exit0;
	}

	//����ת�̹�����
	MMOLOG_PROCESS_ERROR(g_MakePointTurnMgrMgr());
	if (!g_GetPointTurnMgrMgr()->Init())
	{
		LogErrPrint("[center] point turn mgr init fail");
		goto Exit0;
	}

	//���� ����Ҫ�ŵ�����֮�󣬹����������֮�󣬻���һЩ��ʱ�߼���������ģ�鹤��㲥��
	MMOLOG_PROCESS_ERROR(g_MakeUnionMgr());
	if (!g_GetUnionMgr()->Init())
	{
		LogErrPrint("[center] union mgr init fail");
		goto Exit0;
	}

	//Ѻ��
	MMOLOG_PROCESS_ERROR(g_MakeEscortMgr());
	if (!g_GetEscortMgr()->Init())
	{
		LogErrPrint("[center] escortmgr mgr init fail");
		goto Exit0;
	}

	//�ϵͳ
	MMOLOG_PROCESS_ERROR(g_MakeActivityMgr());
	if (!g_GetActivityMgr()->Init())
	{
		LogErrPrint("[center] activity mgr init fail");
		goto Exit0;
	}

	//֪ͨ�㲥ϵͳ
	MMOLOG_PROCESS_ERROR(g_MakeCNotifyMgr());
	if (!g_GetCNotifyMgr()->Init())
	{
		LogErrPrint("[center] CNotify mgr init fail");
		goto Exit0;
	}

	MMO_PROCESS_ERROR(g_MakeCenterSceneMgr());
	MMO_PROCESS_ERROR(g_GetCenterSceneMgr()->Init());
	MMO_PROCESS_ERROR(g_MakeCenterAccountMgr());
	MMO_PROCESS_ERROR(g_GetCenterAccountMgr()->Init());	
	MMOLOG_PROCESS_ERROR(g_MakeWebCenterMgr());
	MMOLOG_PROCESS_ERROR(g_GetWebCenterMgr()->Init());

	MMOLOG_PROCESS_ERROR(g_MakePayCenterMgr());
	MMOLOG_PROCESS_ERROR(g_GetPayCenterMgr()->Init());

	MMOLOG_PROCESS_ERROR(g_MakeCompeteMgr());
	MMOLOG_PROCESS_ERROR(g_GetCompeteMgr()->Init());

	//��ʼ��ÿ�����ݸ��¶�ʱ��
	MMOLOG_PROCESS_ERROR(_InitDataUpdateTimer());

	retCode = _ListenAddress();
	MMOLOG_PROCESS_ERROR(retCode);

	snprintf(m_srvTotalName, SERVER_NAME, "zone%d_center", m_zid);
	LogInfoFmtPrint("%s started ...", m_srvTotalName);

	SetRuningStatus(STATUS_RUNNING);
	result = true;
Exit0:
	if (!result)
	{
		UnInit();
	}
	return result;
}

bool CenterService::_ListenAddress() 
{
	bool result = false;
	ConnectPeer peer;

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_ASSERT_EXIT(m_listenPort != 0);

	peer.ip = m_listenIp;
	peer.port = m_listenPort;
	peer.req = (void*)CenterService::_OnAcceptServer;
	peer.context = this;
	peer.sub_func = SubServerNetPack;
	peer.recvBufSize = INNER_RECVBUF_DEFAULT_SIZE;
	peer.sendBufSize = INNER_SENDBUF_DEFAULT_SIZE;

	m_listenHandle = m_net->Listen(&peer);
	if (m_listenHandle == NULL) 
	{
		LogErrFmtPrint("[center] listen(%s:%d) fail", m_listenIp, m_listenPort);
		goto Exit0;
	}
	LogInfoFmtPrint("[center] listen(%s:%d) success", m_listenIp, m_listenPort);
	result = true;
Exit0:
	return result;
}

bool CenterService::_OnAcceptServer(ISession* session, void* context) 
{
	PROFILE_SEGMENT("CenterService::_OnAcceptServer");

	bool result = false;
	CenterService *service = NULL;

	MMOLOG_ASSERT_EXIT(session != NULL);
	MMOLOG_ASSERT_EXIT(context != NULL);

	service = (CenterService *)context;
	session->SetUserReq((void*)CenterService::_OnCloseServer, context);
	//session->SetNetPackHandle((void*)&service->m_netPackHandle);
	session->SetNetPackHandle((void*)service->GetServiceMessageDispatch());

	service->ResetSessionTimeOut(session, MAX_SERVER_TIME_MSEC);

	LogInfoFmtPrint("[center] accept server. session=%p, address=%s", session, session->GetRemoteAddress().IPAndPort);

	result = true;
Exit0:
	return result;
}

bool CenterService::_OnCloseServer(ISession* session, void* context, CloseFlag flag) 
{
	bool result = false;
	CenterService*    service = NULL;
	ServiceConnect*   serviceConnect = NULL;
	uint32_t          serverID = 0;
	std::string       sessionName = "unknown";
	ServiceType       serviceType = SERVER_TYPE_NULL;
	SESSION_USER_DATA userData;

	MMOLOG_ASSERT_EXIT(session != NULL);
	MMOLOG_ASSERT_EXIT(context != NULL);
	service = (CenterService *)context;
	userData = session->GetUserData();
	serverID = userData.v32;
	serviceType = (ServiceType)session->GetMark();

	switch (serviceType) 
	{
	case GATE_SERVER:
		serviceConnect = service->GetGateConnect(serverID);
		MMOLOG_PROCESS_ERROR(serviceConnect != nullptr);

		serviceConnect->session = nullptr;
		serviceConnect->connectState = CONNECT_STATE_READY;
		break;
	case DBPROXY_SERVER:
		service->m_dbProxyServer.session = nullptr;
		service->m_dbProxyServer.connectState = CONNECT_STATE_READY;
		service->OnDBproxyDisconnect();
		break;
	case LOG_SERVER:
		service->m_logServer.session = nullptr;
		service->m_logServer.connectState = CONNECT_STATE_READY;
		break;
	case LOGIC_SERVER:
		service->m_logicSessionMap.erase(serverID);
		//service->OnLogicDisconnect(serverID);
		//g_GetCenterSceneMgr()->LogicDisConnect(serverID);
		break;
	case WEB_OPERATE_SERVER:
		service->m_webOpServer.session = nullptr;
		service->m_webOpServer.connectState = CONNECT_STATE_READY;
		break;
	case WEB_PAY_SERVER:
		service->m_webPayServer.session = nullptr;
		service->m_webPayServer.connectState = CONNECT_STATE_READY;
		break;
	default:
		MMOLOG_PROCESS_ERROR(false);
		goto Exit0;
		break;
	}
	if (serviceType > SERVER_TYPE_NULL && serviceType < SERVICE_COUNT)
	{
		sessionName = s_service_name[serviceType];
	}
	else if (serviceType > WEB_SERVER_TYPE_NULL && serviceType < WEB_SERVICE_COUNT)
	{
		sessionName = s_web_service_name[serviceType % 100];
	}

	LogInfoFmtPrint("[center] %s(id:%u,ip:%s) closed(%d)",
					sessionName.c_str(),
					serverID,
					session->GetRemoteAddress().IPAndPort,
					flag);
	result = true;
Exit0:
	return result;
}

void CenterService::OnDBproxyDisconnect()			//DB�Ͽ�����
{
	g_GetArenaMgr()->OnDBDisconnect();
}

bool CenterService::IsConnectDBProxy() 
{
	return m_dbProxyServer.connectState == CONNECT_STATE_CONNECTED &&
		m_dbProxyServer.session != nullptr;
}

bool CenterService::SendDataToClient(CharIDType charId, uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;

	char* packBuf = nullptr;
	uint32_t length = 0;
	UidGameInfo* pUid = NULL;
	ServiceConnect* gateCon = nullptr;

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);

	pUid = g_GetCenterAccountMgr()->GetUidGameInfoByCid(charId);

	//�����������ӡ�˴�����,��Ϊ���һЩû���ߵ���ҷ�������
	if (!pUid || pUid->state >= UID_STATE_LOGOUT || pUid->clientId <= 0)
	{
		return false;
	}

	gateCon = GetGateConnect(pUid->gateId);
	MMOLOG_PROCESS_ERROR(gateCon != nullptr);
	MMOLOG_PROCESS_ERROR(gateCon->session != NULL);

	retCode = PackDataWithPreData(module, command, buf, &packBuf, &length, &pUid->clientId);
	MMO_PROCESS_ERROR(retCode);
	 
	retCode = m_net->Send(gateCon->session, packBuf, length);
	MMO_PROCESS_ERROR(retCode);

	result = true;
Exit0:
	return result;
}

bool CenterService::SendDataToClient(SET_UINT64 &setCharID, uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	if (setCharID.size() <= 0)
	{
		return false;
	}

	bool result = false;
	bool retCode = false;

	char* packBuf = nullptr;
	char* finalPackBuf = nullptr;

	uint32_t length = 0;
	MAP_UINT32_LST_UINT32 gateClientsMap;
	MAP_UINT32_LST_UINT32::iterator iter;
	ServiceConnect* gateConn = nullptr;

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);

	g_GetCenterAccountMgr()->GetClientLst(gateClientsMap, setCharID);
	MMOLOG_PROCESS_ERROR(!gateClientsMap.empty());

	//�ȴ�һ�����ݰ����ٸ��ݲ�ͬ����ڲ�ͬ���طֱ���ǰ�����ݰ�,��������������ÿ�ζ�������ݰ�
	retCode = PackData(module, command, buf, &packBuf, &length);
	MMOLOG_PROCESS_ERROR(retCode);

	for (iter = gateClientsMap.begin(); iter != gateClientsMap.end(); iter++)
	{
		//��ǰ�����ݣ�����Ҫ�ȵ���PackData
		RepackWithPreData(&finalPackBuf, length, iter->second);

		gateConn = GetGateConnect(iter->first);
		if (gateConn == nullptr)
		{
			LogErrFmtPrint("cannt send data to gate, gate connect == null, gateId:%d, cmd:%d", iter->first, command);
			continue;
		}
		if (gateConn->session == nullptr)
		{
			LogErrFmtPrint("cannt send data to gate, gate session == null, gateId:%d, cmd:%d", iter->first, command);
			continue;
		}

		retCode = m_net->Send(gateConn->session, finalPackBuf, length);
		if (!retCode)
			LogErrFmtPrint("cannt send data to gate, gateId:%d, cmd:%d", iter->first, command);

		packBuf = nullptr;
		length  = 0;
	}

	result = true;
Exit0:
	return result;
}

bool  CenterService::SendDataToAllClient(uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;
	char* packBuf = nullptr;
	uint32_t length = 0;

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);

	retCode = PackDataWithPreData(module,command, buf, &packBuf, &length);
	MMO_PROCESS_ERROR(retCode);

	for (CONNECT_MAP::iterator iter = m_gateConnectMap.begin(); iter != m_gateConnectMap.end(); iter++)
	{
		if (iter->second.session == nullptr)
		{
			LogErrFmtPrint("SendDataToAllClient, gate session == null, gateId:%d, cmd:%d", iter->first, command);
			continue;
		}
		retCode = m_net->Send(iter->second.session, packBuf, length);
		if (!retCode)
			LogErrFmtPrint("SendDataToAllClient, send data to gate err, gateId:%d, cmd:%d", iter->first, command);
	}

	result = true;
Exit0:
	return result;
}

bool CenterService::SendDataToClientUnchecked(uint32_t gateId, uint32_t clientId, uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;

	char* packBuf = nullptr;
	uint32_t length = 0;
	ServiceConnect* gateConn = GetGateConnect(gateId);

	MMOLOG_PROCESS_ERROR(gateConn != nullptr);
	MMOLOG_PROCESS_ERROR(gateConn->session != nullptr);

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);

	retCode = PackDataWithPreData(module, command, buf, &packBuf, &length, &clientId);
	MMO_PROCESS_ERROR(retCode);

	retCode = m_net->Send(gateConn->session, packBuf, length);
	MMO_PROCESS_ERROR(retCode);

	result = true;
Exit0:
	return result;
}

bool CenterService::SendDataToWebOperate(uint32_t cmd, ProtoBufBase* buf)
{
    bool result = false;
    bool retCode = false;
	MMOLOG_PROCESS_ERROR(m_webOpServer.session != nullptr);

	//��Ӫ������̨û��ģ��ID�������0����ν
	retCode = SendDataEx(m_webOpServer.session, 0, cmd, buf);
	MMOLOG_PROCESS_ERROR(retCode);
	result = true;
Exit0:
	return result;
}

bool CenterService::SendDataToWebOperate(const char* data, uint32_t len)
{
    bool result = false;
    bool retCode = false;
	MMOLOG_PROCESS_ERROR(m_webOpServer.session != nullptr);

	retCode = m_net->Send(m_webOpServer.session, data, len);
	MMOLOG_PROCESS_ERROR(retCode);

    result = true;
Exit0:
	return result;
}

bool CenterService::SendDataToWebPay(uint32_t cmd, ProtoBufBase* buf)
{
    bool result = false;
    bool retCode = false;
	MMOLOG_PROCESS_ERROR(m_webPayServer.session != nullptr);

	retCode = SendDataEx(m_webPayServer.session, EMODULE_ID_PAY, cmd, buf);
	MMOLOG_PROCESS_ERROR(retCode);
	result = true;
Exit0:
	return result;
}

bool  CenterService::SendDataToGate(uint32_t gateId, uint32_t module, uint32_t cmd, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;
	ServiceConnect* gateConn = GetGateConnect(gateId);
	MMOLOG_PROCESS_ERROR(gateConn != nullptr);
	MMOLOG_PROCESS_ERROR(gateConn->session != nullptr);

	retCode = SendDataEx(gateConn->session, module, cmd, buf);
	MMOLOG_PROCESS_ERROR(retCode);
	result = true;
Exit0:
	return result;
}

bool  CenterService::SendDataToAllGate(uint32_t module, uint32_t cmd, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;
	//ServiceConnect* gateConn = nullptr;
	for (auto iter = m_gateConnectMap.begin(); iter != m_gateConnectMap.end(); iter++)
	{
		if (iter->second.session == nullptr)
		{
			LogErrFmtPrint("SendDataToAllGate, send data err, cmd:%d", cmd);
			continue;
		}
		//����Ͳ�������Ż�����Ϊ�������ص�����û����
		retCode = SendDataEx(iter->second.session, module, cmd, buf);
		MMOLOG_PROCESS_ERROR(retCode);
	}

	result = true;
Exit0:
	return result;
}

bool  CenterService::SendDataToLogic(uint32_t logicId, uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;
	char* retbuf = nullptr;
	uint32_t length = 0;
	ISession* psession = GetLogicSession(logicId);

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);
	MMOLOG_PROCESS_ERROR(psession != NULL);

	retCode = PackDataEx(module, command, buf, &retbuf, &length);
	MMOLOG_PROCESS_ERROR(retCode);

	retCode = m_net->Send(psession, retbuf, length);
	MMO_PROCESS_ERROR(retCode);
	result = true;
Exit0:
	return result;
}

bool CenterService::SendDataToLogicByCharID(CharIDType charId, uint16_t module, uint16_t commond, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;
	char* retbuf = nullptr;
	uint32_t length = 0;

	ISession* psession = nullptr;
	uint32_t logicId = 0;

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	if (buf == nullptr)
	{
		LogErrFmtPrint("SendDataToLogicByCharID buf == null, cmd:%d, module:%d, charid:%lu", commond, module, charId);
		MMOLOG_PROCESS_ERROR(buf != NULL);
	}
	
	logicId = g_GetCenterAccountMgr()->GetLogicIdByCid(charId);
	psession = GetLogicSession(logicId);
	if (psession == nullptr)
	{
		LogErrFmtPrint("SendDataToLogicByCharID psession == null, cmd:%d, module:%d, charid:%lu, logicId:%d", commond, module, charId, logicId);
		MMOLOG_PROCESS_ERROR(psession != NULL);
	}

	retCode = PackDataEx(module, commond, buf, &retbuf, &length);
	MMOLOG_PROCESS_ERROR(retCode);

	retCode = m_net->Send(psession, retbuf, length);
	MMO_PROCESS_ERROR(retCode);
	result = true;
Exit0:
	return result;
}

bool  CenterService::SendDataToAllLogic(uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;

	SESSION_MAP::iterator iter = m_logicSessionMap.begin();
	SESSION_MAP::iterator iterEnd = m_logicSessionMap.end();

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);
	for (; iter != iterEnd; iter++)
	{
		retCode = SendDataToLogic(iter->first, module, command, buf);
	}
	MMOLOG_PROCESS_ERROR(retCode);

	result = true;
Exit0:
	return result;

}

bool  CenterService::SendDataToLogic(SET_UINT64 &setCharID, uint16_t module, uint16_t command, ProtoBufBase* buf )
{
	bool result = false;
	bool retCode = false;

	uint32_t logicId = 0;
	ISession* pSession = nullptr;
	char* retbuf = nullptr;
	uint32_t length = 0;

	auto iter = setCharID.begin();
	auto iterEnd = setCharID.end();

	MMOLOG_ASSERT_EXIT(m_net != NULL);
	MMOLOG_PROCESS_ERROR(buf != NULL);

	retCode = PackDataEx(module, command, buf, &retbuf, &length);
	MMOLOG_PROCESS_ERROR(retCode);

	for (; iter != iterEnd; iter++)
	{
		logicId = g_GetCenterAccountMgr()->GetLogicIdByCid(*iter);
		pSession = GetLogicSession(logicId);

		if (pSession == nullptr)
		{
			LogErrFmtPrint("SendDataToLogic with setCharIDs, err, cmd:%d, cid:%lu", command, *iter);
			continue;
		}

		retCode = m_net->Send(pSession, retbuf, length);
		if (!retCode)
			LogErrFmtPrint("SendDataToLogic with setCharIDs, cant send data, cmd:%d, cid:%lu", command, *iter);
	}

	result = true;
Exit0
:
	return result;
}

bool  CenterService::SendDataToDBProxy(uint16_t module, uint16_t command, ProtoBufBase* buf)
{
	bool result = false;
	bool retCode = false;

	if (m_dbProxyServer.session == NULL || m_dbProxyServer.connectState != CONNECT_STATE_CONNECTED)
	{
		LogErrPrint("[center] send data to dbproxy server fail session is invalid");
		return false;
	}

	retCode = SendDataEx(m_dbProxyServer.session, module, command, buf);
	MMOLOG_PROCESS_ERROR(retCode);

	result = true;
Exit0:
	return result;
}

bool CenterService::SendLogToLogServer(JsonObject& json)
{
	bool result = false;
	bool retCode = false;
	string logstr = json.ToString();
	retCode = SendDataNoProtobuf(SERVER_INTERNAL_LOG, EMODULE_ID_SERV_SYS, m_logServer.session, logstr.c_str(), logstr.size());
	MMOLOG_PROCESS_ERROR(retCode);
	result = true;
Exit0:
	return result;
}

bool CenterService::_LoadConfig(const char* config_file) 
{
	bool result = false;
	bool retCode = false;
	LuaParser  parser;

	MMOLOG_ASSERT_EXIT(config_file);
	MMOLOG_ASSERT_EXIT(parser.OpenFile(config_file));
	{
		LuaRef  center = parser.GetRef("Center");
		MMOLOG_PROCESS_ERROR(center.isTable());
		LuaRef  connect = center["ConnectServers"];
		MMOLOG_PROCESS_ERROR(connect.isTable());

		retCode = LoadConfigConnect2Service(connect, "Log", &m_logServer);
		MMOLOG_PROCESS_ERROR(retCode);
		m_logServer.connectState = CONNECT_STATE_READY;

		retCode = LoadConfigConnect2Service(connect, "CharDB", &m_dbProxyServer);
		MMOLOG_PROCESS_ERROR(retCode);
		m_dbProxyServer.connectState = CONNECT_STATE_READY;

		retCode = LoadConfigConnect2Service(connect, "WebOp", &m_webOpServer);
		MMOLOG_PROCESS_ERROR(retCode);
		m_webOpServer.connectState = CONNECT_STATE_READY;

		retCode = LoadConfigConnect2Service(connect, "WebPay", &m_webPayServer);
		MMOLOG_PROCESS_ERROR(retCode);
		m_webPayServer.connectState = CONNECT_STATE_READY;

		retCode = LoadConfigConnectMap2Service(connect, "Gate", m_gateConnectMap);
		MMOLOG_PROCESS_ERROR(retCode);

		retCode = GetLuaTableValue(center, "ID", &m_id);
		MMOLOG_PROCESS_ERROR(retCode);

		retCode = GetLuaTableValue(center, "IP", m_listenIp, countof(m_listenIp));
		MMOLOG_PROCESS_ERROR(retCode);

		retCode = GetLuaTableValue(center, "Port", &m_listenPort);
		MMOLOG_PROCESS_ERROR(retCode);

		retCode = GetLuaTableValue(center, "Zid", &m_zid);
		MMOLOG_PROCESS_ERROR(retCode);

		retCode = GetLuaTableValue(center, "TokenTimeCheck", &m_tokenCheck);
		if (retCode == false)
			m_tokenCheck = false;

#ifdef WIN32
		double tmpTime = 0;
		retCode = GetLuaTableValue(center, "OpenTime", &tmpTime);
		m_openTime = (uint64_t)tmpTime;
		MMOLOG_PROCESS_ERROR(retCode);
#else
		retCode = GetLuaTableValue(center, "OpenTime", &m_openTime);
		MMOLOG_PROCESS_ERROR(retCode);
#endif

		retCode = m_zid > 0 && m_id > 0;
		MMO_PROCESS_ERROR(retCode);

		retCode = parser.GetValue<uint32_t>("OpenGM", &m_bOpenGMFlag);
		MMOLOG_PROCESS_ERROR(retCode);

		int32_t checkping = 0;
		if (GetLuaTableValue(center, "CheckPing", &checkping))
		{
			m_checkPing = (bool)checkping;
		}
	}

	result = true;
Exit0:
	return result;
}
uint32_t   CenterService::GetOpenGMFlag()
{
	return m_bOpenGMFlag;
}
void  CenterService::UnInit()
{
	if (m_listenHandle != nullptr) 
	{
		m_net->CloseListen(m_listenHandle);
		m_listenHandle = nullptr;
	}

	if (g_GetCSScriptMgr())
	{
		g_GetCSScriptMgr()->UnInit();
		g_DelCSScriptMgr();
	}

	if (g_GetRelationMgr())
	{
		g_GetRelationMgr()->UnInit();
		g_DelRelationMgr();
	}

	if (g_GetMailMgr())
	{
		g_GetMailMgr()->UnInit();
		g_DelMailMgr();
	}

	if (g_GetChatCenter())
	{
		g_GetChatCenter()->UnInit();
		g_DelChatCenter();
	}

	if (g_GetCenterDuplicateMgr())
	{
		g_GetCenterDuplicateMgr()->UnInit();
		g_DelCenterDuplicateMgr();
	}

	if (g_GetRoomMgr())
	{
		g_GetRoomMgr()->UnInit();
		g_DelRoomMgr();
	}
	if (g_GetCampMgr())
	{
		g_GetCampMgr()->UnInit();
		g_DelCampMgr();
	}

/*
	if (g_GetMallMgr())
	{
		g_GetMallMgr()->UnInit();
		g_DelMallMgr();
	}*/

	if (g_GetTeamMgr())
	{
		g_GetTeamMgr()->UnInit();
		g_DelTeamMgr();
	}

	if (g_GetArenaMgr())
	{
		g_GetArenaMgr()->UnInit();
		g_DelArenaMgr();
	}

	if (g_GetMirrorMgr())
	{
		g_GetMirrorMgr()->UnInit();
		g_DelMirrorMgr();
	}

	if (g_GetGlobalMgr())
	{
		g_GetGlobalMgr()->UnInit();
		g_DelGlobalMgr();
	}

	if (g_GetRankingListMgr())
	{
		g_GetRankingListMgr()->UnInit();
		g_DelRankingListMgr();
	}

	if (g_GetCenterAuctioneerMgr())
	{
		g_GetCenterAuctioneerMgr()->UnInit();
		g_DelCenterAuctioneerMgr();
	}

	if (g_GetGMMgr())
	{
		g_GetGMMgr()->UnInit();
		g_DelGMMgr();
	}
		
	if (g_GetQueryMgr())
	{
		g_GetQueryMgr()->UnInit();
		g_DelQueryMgr();
	}

	if (g_GetPointTurnMgrMgr())
	{
		g_GetPointTurnMgrMgr()->UnInit();
		g_DelPointTurnMgrMgr();
	}

	//����
	if (g_GetUnionMgr())
	{
		g_GetUnionMgr()->UnInit();
		g_DelUnionMgr();
	}

	//�̳ǵ�ж��Ҫ�ŵ�����֮�󣬹��ᱣ���ʱ�����̳�ȡһ������
	if (g_GetMallMgr())
	{
		g_GetMallMgr()->UnInit();
		g_DelMallMgr();
	}

	if (g_GetEscortMgr())
	{
		g_GetEscortMgr()->UnInit();
		g_DelEscortMgr();
	}

	if (g_GetActivityMgr())
	{
		g_GetActivityMgr()->UnInit();
		g_DelActivityMgr();
	}

	if (g_GetCenterAccountMgr())
	{
		g_GetCenterAccountMgr()->UnInit();
		g_DelCenterAccountMgr();
	}

	CloseServerConnection(m_net, &m_dbProxyServer);
	CloseServerConnection(m_net, &m_logServer);
	for (auto iter = m_gateConnectMap.begin(); iter != m_gateConnectMap.end(); iter++)
		CloseServerConnection(m_net, &iter->second);

	if (g_GetCenterServerModuleMgr())
	{
		g_GetCenterServerModuleMgr()->UnInit();
		g_DelCenterServerModuleMgr();
	} 

	if (g_GetWebCenterMgr())
	{
		g_GetWebCenterMgr()->UnInit();
		g_DelWebCenterMgr();
	}

	if (g_GetCompeteMgr())
	{
		g_GetCompeteMgr()->UnInit();
		g_DelCompeteMgr();
	}

	if (g_GetActiveCharacterMgr())
	{
		g_GetActiveCharacterMgr()->UnInit();
		g_DelActiveCharacterMgr();
	}

	if (g_GetCNotifyMgr())
	{
		g_GetCNotifyMgr()->UnInit();
		g_DelCNotifyMgr();
	}

	if (g_GetOfflineCharacterDataMgr())
	{
		g_GetOfflineCharacterDataMgr()->UnInit();
		g_DelOfflineCharacterDataMgr();
	}

	MMO_DELETE(m_pMessageDispatch);
	g_GetTimerAxis()->KillAllFixTimer(this);
	g_GetTimerAxis()->KillAllTimer(this);
	m_net = NULL;
}

bool CenterService::Update(uint64_t tick)
{
	bool result = false;

	BEGIN_PROFILE("CenterService::_ProcessConnection");
	_ProcessConnection();
	END_PROFILE();

	BEGIN_PROFILE("CenterService::_SyncServiceState");
	_SyncServiceState();
	END_PROFILE();

	BEGIN_PROFILE("CenterService::_CheckDayChange");
	_CheckDayChange();
	END_PROFILE();

	BEGIN_PROFILE("ActiveCharacterMgr::Update");
	g_GetActiveCharacterMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("OfflineCharacterDataMgr::Update");
	g_GetOfflineCharacterDataMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("CSScriptMgr::Update");
	g_GetCSScriptMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("RelationMgr::Update");
	g_GetRelationMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("g_GetMailMgr::Update");
	g_GetMailMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("g_GetCenterAccountMgr::Update");
	g_GetCenterAccountMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("g_GetSceneMgr::Update");
	g_GetCenterSceneMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("g_GetArenaMgr::Update");
	g_GetArenaMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("g_GetActivityMgr::Update");
	g_GetActivityMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("g_GetCompeteMgr::Update");
	g_GetCompeteMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("g_GetCampMgr::Update");
	g_GetCampMgr()->Update(tick);
	END_PROFILE();

	BEGIN_PROFILE("CenterService::SendErrLog");
	if (ServerTime::CheckPerSecs(120)) 
	{
		SendErr(m_logServer.session, EMODULE_ID_SERV_SYS, SERVER_ERR_LOG_COLLECT);
	}
	END_PROFILE();

	if (IsQuitting() && _CheckQuittingComplete()) 
	{
		goto Exit0;
	}

	result = true;

Exit0:
	_CheckLuaStackLeak();
	return result;
}

bool CenterService::_ProcessConnection() 
{
	bool retCode = false;
	time_t timeInSecond = Time::Now().UnixSec();

	// dbproxy
	retCode = ConnectService(m_net, &m_dbProxyServer, timeInSecond, CenterService::_OnConnectDBProxyServer, this);
	MMOLOG_OUTPUT_ERROR(retCode);

	// webCenter
	retCode = ConnectService(m_net, &m_webOpServer, timeInSecond, CenterService::_OnConnectOpWebServer, this);
	MMOLOG_OUTPUT_ERROR(retCode);

	// payWebCenter
	retCode = ConnectService(m_net, &m_webPayServer, timeInSecond, CenterService::_OnConnectPayWebServer, this);
	MMOLOG_OUTPUT_ERROR(retCode);

	// log
	retCode = ConnectService(m_net, &m_logServer, timeInSecond, CenterService::_OnConnectLogServer, this);
	MMOLOG_OUTPUT_ERROR(retCode);

	//gate
	CONNECT_MAP::iterator iter = m_gateConnectMap.begin();
	for (; iter != m_gateConnectMap.end(); iter++)
	{
		retCode = ConnectService(m_net, &iter->second, timeInSecond, CenterService::_OnConnectGateServer, &iter->second);
		MMOLOG_OUTPUT_ERROR(retCode);
	}

	return true;
}

bool CenterService::_SyncServiceState() 
{
	bool retCode = false;
	uint64_t tick = Time::Tick();

	if (tick < m_syncStateTick + SERVER_PING_INTERVAL * 1000)
		return true;
	
	if (m_dbProxyServer.connectState == CONNECT_STATE_CONNECTED) 
	{
		retCode = SendData(m_dbProxyServer.session,EMODULE_ID_SERV_SYS, DBPROXY_PROTOCOL_PING_REQ);
		MMOLOG_OUTPUT_ERROR(retCode);
	}

	if (m_logServer.connectState == CONNECT_STATE_CONNECTED)
	{
		retCode = SendData(m_logServer.session, EMODULE_ID_SERV_SYS, LOG_SERVER_PROTOCOL_PING);
		MMOLOG_OUTPUT_ERROR(retCode);
	}

	if (m_webOpServer.connectState == CONNECT_STATE_CONNECTED)
	{
		retCode = SendData(m_webOpServer.session, EMODULE_ID_SERV_SYS, CENTER_TO_WEBOP_PING);
		MMOLOG_OUTPUT_ERROR(retCode);
	}

	if (m_webPayServer.connectState == CONNECT_STATE_CONNECTED)
	{
		retCode = SendData(m_webPayServer.session, EMODULE_ID_SERV_SYS, CENTER_TO_WEBPAY_PING);
		MMOLOG_OUTPUT_ERROR(retCode);
	}

	if (m_gateConnectMap.empty())
		LogErrFmtPrint("[center] gate connects empty, it's unnormal...");

	CONNECT_MAP::iterator iter = m_gateConnectMap.begin();
	for (; iter != m_gateConnectMap.end(); iter++)
	{
		if (iter->second.connectState == CONNECT_STATE_CONNECTED)
		{
			retCode = SendData(iter->second.session, EMODULE_ID_SERV_SYS, GATE_SERVER_PROTOCOL_PING);
			MMOLOG_OUTPUT_ERROR(retCode);
		}
	}
	m_syncStateTick = tick;
	return true;
}

bool CenterService::_CheckDayChange() 
{
	if (IsQuitting()) 
	{
		return false;
	}

	/*bool isDayChange = false;
	bool isWeekChange = false;
	uint64_t unixSec = ServerTime::UnixSec();
	isDayChange = TimeUtility::CheckDayChange(unixSec, m_lastDayChangeTime, &isWeekChange);
	if (!isDayChange) 
	{
		return false;
	}
	LogInfoFmtPrint("[center] CenterService::_CheckDayChange daychange=%d, weekchange=%d, lasttime=%llu, curtime=%llu",
					isDayChange,
					isWeekChange,
					m_lastDayChangeTime,
					unixSec);

	m_lastDayChangeTime = unixSec;
	// ע�⣬�����¼���˵�ǰ���ݶ�Ӧ���죬���ڸ���ģ���ڲ���Ϊδ������Ƿ�0�㻻������´���ռ�
	m_curDay = Time::GetLocalDate().year * 365 + Time::GetLocalDate().yday;
	_OnDayChange(m_curDay);

	if (!isWeekChange)
	{
		return false;
	}
	_OnWeekChange();*/

	return true;
}

bool CenterService::_InitDataUpdateTimer()
{
	g_GetTimerAxis()->KilFixTimer(ETimer_ID_Data_Update, this);
	g_GetTimerAxis()->KilFixTimer(ETimer_ID_ZeroClock_Update, this);	
	int32_t updateTime = 0;
	const ConstantConstantCfgInfo *pConstCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_ServerUpdateTime);
	if (nullptr != pConstCfg)
	{
		updateTime = pConstCfg->constantdata * 3600;
	}
	if (updateTime < 0)//���ʱ������ʼʱ�䣬����С��0
	{
		updateTime = 0;
	}
	//ָ��ʱ����µĶ�ʱ��
	if (!g_GetTimerAxis()->SetFixTimer(ETimer_ID_Data_Update, updateTime, 1, this))
	{
		LogErrFmtPrint("[center] _InitDataUpdateTimer...SetFixTimer failed...updateTime:%d ", updateTime);
		return false;
	}
	//0�㶨ʱ��
	if (!g_GetTimerAxis()->SetFixTimer(ETimer_ID_ZeroClock_Update, 0, 1, this))
	{
		LogErrFmtPrint("[center] _InitDataUpdateTimer...Set ZeroClock Timer failed...");
		return false;
	}

	//ping
	if (m_checkPing)
	{
		if (!g_GetTimerAxis()->SetTimer(ETimer_ID_Check_Ping, 3 * 1000, this))
		{
			LogErrFmtPrint("[center] _InitDataUpdateTimer...Set CheckPing Timer failed...");
			return false;
		}
	}
	
	//
	LogInfoFmtPrint("[center] _InitDataUpdateTimer..success...updateTime:%d, m_checkPing:%d ", updateTime, m_checkPing);

	return true;
}

void CenterService::_OnDataUpdate()
{
	if (IsQuitting())
	{
		return;
	}
	uint64_t unixSec = ServerTime::UnixSec();
	LogInfoFmtPrint("[center] _OnDataUpdate....everday update....unixSec:%lu ", unixSec);
	//ÿ�ո���
	_OnDayChange(0);
	//�������һ����ʾÿ�ܸ���
	Date nowTime = Time::GetLocalDate();
	if (1 == nowTime.wday) /* days since Sunday - [0,6] */
	{
		LogInfoFmtPrint("[center] _OnDataUpdate....week update....unixSec:%lu ", unixSec);
		_OnWeekChange();
	}	
}

void CenterService::_OnZeroClockUpdate()
{
	if (IsQuitting())
	{
		return;
	}
	uint64_t unixSec = ServerTime::UnixSec();
	LogInfoFmtPrint("[center] _OnZeroClockUpdate....everday  zeroclock update....unixSec:%lu ", unixSec);
	//ÿ��������
	_OnDayZeroChange();
	//�������һ����ʾÿ��������
	Date nowTime = Time::GetLocalDate();
	if (1 == nowTime.wday) /* days since Sunday - [0,6] */
	{
		LogInfoFmtPrint("[center] _OnZeroClockUpdate....week zeroclock....unixSec:%lu ", unixSec);
		//ÿ��һ������
		_OnWeekZeroChange();
	}
}

void CenterService::_OnDayChange(uint32_t curDay) 
{
	g_GetCampMgr()->DailyUpdate();
	g_GetUnionMgr()->DailyUpdate();
	g_GetEscortMgr()->DailyUpdate();
	g_GetMallMgr()->DailyUpdate();
	g_GetRankingListMgr()->DailyUpdate();
	CenterDailyUpdateNotify notify;
	uint64_t unixSec = ServerTime::UnixSec();
	notify.set_updatedailytime(unixSec);
	SendDataToAllLogic(EMODULE_ID_ACTIVITY, CENTER_TO_LOGIC_DAILY_UPDATE_NOTIFY, &notify);
	//
	_NotifyDataFresh(EDataFreshType_Day);
}

void CenterService::_OnWeekChange()
{
	g_GetCampMgr()->WeekUpdate();
	g_GetUnionMgr()->WeekUpdate();
	g_GetEscortMgr()->WeekUpdate();
	CenterWeekUpdateNotify notify;
	uint64_t unixSec = ServerTime::UnixSec();
	notify.set_updatedailytime(unixSec);
	SendDataToAllLogic(EMODULE_ID_ACTIVITY, CENTER_TO_LOGIC_WEEK_UPDATE_NOTIFY, &notify);
	//
	_NotifyDataFresh(EDataFreshType_Week);
}

void CenterService::_OnDayZeroChange()
{
	uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
	//���㿪������������
	_CalcDayCountFromOpen(curTime);


	g_GetRankingListMgr()->DayTick();

	CenterDayTickNotify notify;
	uint64_t unixSec = ServerTime::UnixSec();
	notify.set_updatedailytime(unixSec);
	SendDataToAllLogic(EMODULE_ID_ACTIVITY, CENTER_TO_LOGIC_DAILY_ZERO_UPDATE_NOTIFY, &notify);

	_NotifyDataFresh(EDataFreshType_DayZero);
}

void CenterService::_OnWeekZeroChange()
{
	CenterWeekZeroUpdateNotify notify;
	uint64_t unixSec = ServerTime::UnixSec();
	notify.set_updatedailytime(unixSec);
	SendDataToAllLogic(EMODULE_ID_ACTIVITY, CENTER_TO_LOGIC_WEEK_ZERO_UPDATE_NOTIFY, &notify);
	//
	_NotifyDataFresh(EDataFreshType_WeekZero);
}

void CenterService::_CalcDayCountFromOpen(uint64_t curTime)
{
	//���㿪����һ�컹ʣ���ʱ��
	Date curDate = Time::GetLocalDate(m_openTime);
	uint64_t openDaySec = curDate.hour * 3600 + curDate.min * 60 + curDate.sec;
	uint64_t dayLefSec = (24 * 3600) - openDaySec;

	m_dayCountFromOpen = 1;
	if (curTime >= (m_openTime + dayLefSec))
	{
		uint64_t interSec = curTime - (m_openTime + dayLefSec);
		uint32_t dayCount = 0;
		uint64_t daySec = 24 * 3600;
		dayCount = interSec / daySec;
		if (0 != (interSec % daySec))
		{
			dayCount += 1;
		}
		m_dayCountFromOpen += dayCount;
	}

	LogInfoFmtPrint("[center] CenterService::_CalcDayCountFromOpen....zid:%d, id:%d, m_dayCountFromOpen:%u, curTime:%lu, opentime:%lu ", m_zid, m_id, m_dayCountFromOpen, curTime, m_openTime);
}


ISession* CenterService::GetLogicSession(uint32_t logicId)
{
	SESSION_MAP::iterator iter = m_logicSessionMap.find(logicId);
	SESSION_MAP::iterator iterEnd = m_logicSessionMap.end();
	if (iter == iterEnd)
		return nullptr;
	return iter->second;
}

bool CenterService::_OnConnectDBProxyServer(ISession* session, void* context, bool success)
{
	PROFILE_SEGMENT("CenterService::_OnConnectDBProxyServer");

	bool result = false;
	SESSION_USER_DATA userdata;
	CenterService* service = NULL;
	ServiceConnect* serviceConnect = NULL;

	MMOLOG_ASSERT_EXIT(context != NULL);
	service = (CenterService*)context;
	serviceConnect = &service->m_dbProxyServer;

	if (success) 
	{
		MMOLOG_ASSERT_EXIT(session != NULL);
		serviceConnect->session = session;
		serviceConnect->connectState = CONNECT_STATE_CONNECTED;
		serviceConnect->serviceType = DBPROXY_SERVER;
		serviceConnect->session->SetUserReq((void*)(CenterService::_OnCloseServer), context);
		//serviceConnect->session->SetNetPackHandle((void*)(&service->m_netPackHandle));
		serviceConnect->session->SetNetPackHandle((void*)(service->GetServiceMessageDispatch()));
		LogInfoFmtPrint("[center] connect dbproxy server(id:%u, ip:%s:%d) success",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);

		userdata.v32 = serviceConnect->id;
		session->SetUserData(userdata);
		session->SetMark(DBPROXY_SERVER);

	}
	else 
	{
		LogErrFmtPrint("[center] connect dbproxy server(id:%u, ip:%s:%d) fail",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);
		serviceConnect->connectState = CONNECT_STATE_READY;
	}

	result = true;
Exit0:
	return result;
}

bool CenterService::_OnConnectGateServer(ISession* session, void* context, bool success)
{
	PROFILE_SEGMENT("CenterService::_OnConnectGateServer");

	bool result = false;
	SESSION_USER_DATA userdata;
	ServiceConnect* serviceConnect = NULL;

	MMOLOG_ASSERT_EXIT(context != NULL);
	serviceConnect = (ServiceConnect*)context;

	if (success) 
	{
		MMOLOG_ASSERT_EXIT(session != NULL);
		serviceConnect->session = session;
		serviceConnect->connectState = CONNECT_STATE_CONNECTED;
		serviceConnect->serviceType = GATE_SERVER;
		serviceConnect->session->SetUserReq((void*)(CenterService::_OnCloseServer), context);
		serviceConnect->session->SetNetPackHandle((void*)(g_GetCenterService()->GetServiceMessageDispatch()));
		LogInfoFmtPrint("[center] connect gate server(id:%u, ip:%s:%d) success",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);

		userdata.v32 = serviceConnect->id;
		session->SetUserData(userdata);
		session->SetMark(GATE_SERVER);

		g_GetCenterService()->_Register2Gate(session);
	}
	else 
	{
		LogErrFmtPrint("[center] connect gate server(id:%u, ip:%s:%d) fail",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);
		serviceConnect->connectState = CONNECT_STATE_READY;
	}

	result = true;
Exit0:
	return result;
}

bool CenterService::_OnConnectLogServer(ISession* session, void* context, bool success) 
{
	PROFILE_SEGMENT("CenterService::_OnConnectLogServer");

	bool result = false;
	SESSION_USER_DATA userdata;
	CenterService* service = NULL;
	ServiceConnect* serviceConnect = NULL;

	MMOLOG_ASSERT_EXIT(context != NULL);
	service = (CenterService*)context;
	serviceConnect = &service->m_logServer;

	if (success) 
	{
		MMOLOG_ASSERT_EXIT(session != NULL);
		serviceConnect->session = session;
		serviceConnect->connectState = CONNECT_STATE_CONNECTED;
		serviceConnect->serviceType = LOG_SERVER;
		serviceConnect->session->SetUserReq((void*)(CenterService::_OnCloseServer), context);
		//serviceConnect->session->SetNetPackHandle((void*)(&service->m_netPackHandle));
		serviceConnect->session->SetNetPackHandle((void*)(service->GetServiceMessageDispatch()));
		LogInfoFmtPrint("[center] connect log server(id:%u, ip:%s:%d) success",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);

		userdata.v32 = serviceConnect->id;
		session->SetUserData(userdata);
		session->SetMark(LOG_SERVER);
	}
	else 
	{
		LogErrFmtPrint("[center] connect log server(id:%u, ip:%s:%d) fail",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);
		serviceConnect->connectState = CONNECT_STATE_READY;
	}
	result = true;
Exit0:
	return result;
}

bool CenterService::_OnConnectOpWebServer(ISession* session, void* context, bool success) 
{
	PROFILE_SEGMENT("CenterService::_OnConnectOpWebServer");

	bool result = false;
	SESSION_USER_DATA userdata;
	CenterService* service = NULL;
	ServiceConnect* serviceConnect = NULL;

	MMOLOG_ASSERT_EXIT(context != NULL);
	service = (CenterService*)context;
	serviceConnect = &service->m_webOpServer;

	if (success) 
	{
		MMOLOG_ASSERT_EXIT(session != NULL);
		serviceConnect->session = session;
		serviceConnect->connectState = CONNECT_STATE_CONNECTED;
		serviceConnect->serviceType = WEB_OPERATE_SERVER;
		serviceConnect->session->SetUserReq((void*)(CenterService::_OnCloseServer), context);
		serviceConnect->session->SetNetPackHandle((void*)(service->GetServiceMessageDispatch()));
		LogInfoFmtPrint("[center] connect OpWeb server(id:%u, ip:%s:%d) success",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);

		userdata.v32 = serviceConnect->id;
		session->SetUserData(userdata);
		session->SetMark(WEB_OPERATE_SERVER);
		service->_Register2OpWeb(session);
	}
	else 
	{
		LogErrFmtPrint("[center] connect OpWeb server(id:%u, ip:%s:%d) fail",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);
		serviceConnect->connectState = CONNECT_STATE_READY;
	}
	result = true;
Exit0:
	return result;
}


bool CenterService::_OnConnectPayWebServer(ISession* session, void* context, bool success) 
{
	PROFILE_SEGMENT("CenterService::_OnConnectPayWebServer");

	bool result = false;
	SESSION_USER_DATA userdata;
	CenterService* service = NULL;
	ServiceConnect* serviceConnect = NULL;

	MMOLOG_ASSERT_EXIT(context != NULL);
	service = (CenterService*)context;
	serviceConnect = &service->m_webPayServer;

	if (success) 
	{
		MMOLOG_ASSERT_EXIT(session != NULL);
		serviceConnect->session = session;
		serviceConnect->connectState = CONNECT_STATE_CONNECTED;
		serviceConnect->serviceType = WEB_OPERATE_SERVER;
		serviceConnect->session->SetUserReq((void*)(CenterService::_OnCloseServer), context);
		serviceConnect->session->SetNetPackHandle((void*)(service->GetServiceMessageDispatch()));
		LogInfoFmtPrint("[center] connect PayWeb server(id:%u, ip:%s:%d) success",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);

		userdata.v32 = serviceConnect->id;
		session->SetUserData(userdata);
		session->SetMark(WEB_PAY_SERVER);

		g_GetPayCenterMgr()->RegisterWebPay();
	}
	else 
	{
		LogErrFmtPrint("[center] connect PayWeb server(id:%u, ip:%s:%d) fail",
						serviceConnect->id,
						serviceConnect->remoteIp,
						serviceConnect->remotePort);
		serviceConnect->connectState = CONNECT_STATE_READY;
	}
	result = true;
Exit0:
	return result;
}

// �˳�����
bool CenterService::Quit()
{
	SetRuningStatus(STATUS_QUITTING);

	//�˳���������
	uint64_t start = Time::Tick();
	g_GetRelationMgr()->Update(start, true);
	g_GetArenaMgr()->Update(start, true);
	g_GetMailMgr()->Update(start, true);
	g_GetUnionMgr()->SaveAll();
	g_GetRankingListMgr()->SaveDB(Time::Now().UnixSec());
	g_GetCampMgr()->SaveDB(true);
	g_GetMallMgr()->SaveDB(true);
	return true;
}

// ��֤��ģ���Ƿ�׼�����˳�
bool CenterService::_CheckQuittingComplete()
{
	return true;
}

bool CenterService::_CheckLuaStackLeak()
{
	LuaScript* sc = g_GetCSScriptMgr()->GetScript();
	if (sc == nullptr) 
	{
		return false;
	}
	int topIndex = sc->GetTopIndex();
	if (topIndex == 0) 
	{
		return true;
	}
	LogErrFmtPrint("[center] script stack leak (%d)!", topIndex);
	sc->SetTopIndex(0);
	return false;
}

bool CenterService::HandleConsoleCmd(const char* cmd)
{
	return (cmd[0] != '\0');
}

IMessageDispatch *CenterService::GetServiceMessageDispatch()
{
	return m_pMessageDispatch;
}

void CenterService::OnTimer(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case ETimer_ID_Data_Update:
		{
			_OnDataUpdate();
		}
		break;
	case ETimer_ID_ZeroClock_Update:
		{
			_OnZeroClockUpdate();
		}
		break;
	case ETimer_ID_Check_Ping:
		{
			_CheckServerPing();
		}
		break;
	default:
		break;
	}
}

bool CenterService::AddLogicSession(uint32_t logicId, ISession* pSession)
{
    bool result = false;
    bool retCode = false;
	SESSION_USER_DATA sdata;
	retCode = m_logicSessionMap.insert(SESSION_MAP::value_type(logicId, pSession)).second;
	MMOLOG_PROCESS_ERROR(retCode);

	sdata.v32 = logicId;
	pSession->SetUserData(sdata);
	pSession->SetMark(LOGIC_SERVER);

	//�߼���ע��ʱ������һ��pingʱ��ĳ�ʼ��
	OnServerPing(pSession);

    result = true;
Exit0:
	return result;
}

void CenterService::OnServerPing(ISession* pSession)
{
	if (nullptr == pSession)
	{
		return;
	}
	if (LOGIC_SERVER == pSession->GetMark()) //�߼���
	{
		uint32_t logicId = pSession->GetUserData().v32;
		m_logicPing[logicId] = g_GetGlobalServerTime()->UnixSec();
		//LogDebugFmtPrint("CenterService::OnServerPing...logicid:%u, time:%lu ", logicId, g_GetGlobalServerTime()->UnixSec());
	}
}

void CenterService::_CheckServerPing()
{
	if (IsQuitting())
	{
		return;
	}
	//�������6�ζ�û�յ��߼�����ping��Ϣ������Ϊ�߼�������
	uint32_t timeoutSec = SERVER_PING_INTERVAL * 6;
	uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
	MAP_UINT32_UINT64::iterator iterPing = m_logicPing.begin();
	while (iterPing != m_logicPing.end())
	{
		if (curTime - iterPing->second > timeoutSec)
		{
			_OnLogicCrash(iterPing->first,iterPing->second);
			//��������֮��������Ҫɾ���߼�����pingʱ�䣬�ȴ��߼�������֮���ٴ����������ķ�
			iterPing = m_logicPing.erase(iterPing);
			continue;
		}
		++iterPing;
	}
}

void CenterService::_OnLogicCrash(uint32_t logicId,uint64_t lastPing)
{
	LogErrFmtPrint("[center] CenterService::_OnLogicCrash....logicid:%u,lastPing:%lu  ", logicId,lastPing);
	g_GetCenterDuplicateMgr()->LogicCrash(logicId);
	g_GetCenterSceneMgr()->LogicCrash(logicId);
	g_GetMailMgr()->LogicCrash(logicId);
	//�ʺŵĴ���ŵ���󣬿���ǰ��Ĵ�����Ҫ����Ϣ���ͻ���
	g_GetCenterAccountMgr()->LogicCrash(logicId);
	//�����Ͽ�����
	ISession *pSession = GetLogicSession(logicId);
	if (nullptr != pSession && nullptr != m_net)
	{
		LogInfoFmtPrint("CenterService::_OnLogicCrash...close logic session...logicid:%u ", logicId);
		m_net->Close(pSession);	
	}
}

void CenterService::_NotifyDataFresh(int8_t freshType)
{
	NotifyDataFresh notify;
	notify.set_fresh_type(freshType);
	SendDataToAllClient(EMODULE_ID_PLAYER, LOGIC_TO_CLIENT_NOTIFY_DATA_FRESH, &notify);
}


bool CenterService::_Register2Gate(ISession *pSession)
{
	bool result = false;
	bool retCode = false;
	CenterRegisterGateReq registe;
	registe.set_id(m_id);
	retCode = g_GetCenterService()->SendData(pSession, EMODULE_ID_SERV_SYS, CENTER_REGISTE_GATE_REQ, &registe);
	MMO_PROCESS_ERROR(retCode);
	result = true;
Exit0:
	return result;
}

bool CenterService::_Register2OpWeb(ISession* pSession)
{
    bool result = false;
    bool retCode = false;
	RegisterOperateWebReq reg;
	reg.set_zid(m_zid);
	retCode = g_GetCenterService()->SendData(pSession, EMODULE_ID_SERV_SYS, CENTER_REGSITER_OPWEB_REQ, &reg);
	MMOLOG_PROCESS_ERROR(retCode);
    result = true;
Exit0:
	return result;
}

void CenterService::OnGM(std::vector<std::string> & v)
{
	if (IsRuning() && (int)v.size()>=2)
	{
		LogicGM gm;
		gm.set_cid(0);
		gm.set_channelid(0);
		//gm.set_zid(0);
		gm.set_gmcmd(v[0]);
		for (int i = 2; i < (int)v.size();++i)
		{
			std::string *pStr=gm.add_agrs();
			pStr->assign(v[i].c_str());
		}
		g_GetGMMgr()->OnHangleMsg(CommonApi::StrToInt(v[1]),gm);
	}
}

ServiceConnect* CenterService::GetGateConnect(uint32_t gateId)
{
	CONNECT_MAP::iterator iter = m_gateConnectMap.find(gateId);
	if (iter != m_gateConnectMap.end())
	{
		return &iter->second;
	}
	return nullptr;
}